﻿using System;
using System.Collections.Generic;
using System.Linq;
using T.FAS.Action.Common;
using T.FAS.Action.MetaData.Entity;
using T.FAS.Base.Entity;
using T.FAS.Expression.Entity;
using T.FAS.Runtime.Metadata.SPI;
using T.FAS.Action.Dev.Dao;
using T.FAS.Action.Dev.Entity;
using System.Text;
using DataModelEntity = T.FAS.DataModel.MetaData.Entity;
using DataModelDao = T.FAS.DataModel.MetaData.Dao;
using T.FAS.DataModel.MetaData.Entity;
using T.FAS.MetaData.Entity;
using ActionType = T.FAS.Action.MetaData.Entity.ActionType;
using T.FAS.DataModel.MetaData.Dev.Plugin;
using T.FAS.Studio.DevProject.Service;
using T.FAS.Studio.DevProject.Entity;
using Newtonsoft.Json;
using T.FAS.Studio.SysManager.Service;

namespace T.FAS.Runtime.Action.ExpressionPlugin
{
    public class DataBaseDetailExpProvider : BaseProvider, IExprProvider
    {
        public List<ExprItem> GetExprChildrenItems(List<ExprItem> item, bool IsContainExt, string projectBranchId)
        {
            var list = new List<ExprItem>();
            if (item == null || item.Count <= 0)
                return list;

            foreach (var i in item)
            {
                if (i.IsDelete)
                    continue;
                try
                {
                    UpdateExprItem(i,IsContainExt,projectBranchId);
                }
                catch (Exception ex)
                {
                    i.ItemType = ItemType.Error;
                    i.DisplayName = ex.Message;
                }
            }
            return list;
        }

        public List<ExprItem> GetExprChildrenItems(ExprItem item, bool IsContainExt, string projectBranchId)
        {
            if (item == null)
                throw new ArgumentNullException("DataBaseDetailExpProvider.GetExprChildrenItems.item");
            if(item.ItemType!= ItemType.DataBase)
                throw new ArgumentNullException("DataBaseDetailExpProvider.GetExprChildrenItems.item is not DataBase");
            UpdateExprItem(item,IsContainExt, projectBranchId);
            return item.Children;
        }

        public List<ExprItem> GetExprIncrementalItems(string exprMetaDataID, DateTime dateTime)
        {
            return new List<ExprItem>();
        }

        public List<ExprItem> GetExprItems(string type, string typeId, string exprMetaDataID)
        {
            return new List<ExprItem>();
        }

        #region 内部方法
        private void UpdateExprItem(ExprItem item, bool IsContainExt = false,string projectBranchId="")
        {
            var dbInfos = GetDataBaseInfo(item, projectBranchId);
            if (dbInfos == null)
            {
                item.ItemType = ItemType.Error;
                item.DisplayName = $"未找到{item.Code}数据";
                return;
            }
            if (dbInfos.Details != null && dbInfos.Details.Count > 0)
            {
                //添加表信息
                var tables = dbInfos.Details.FindAll(x=>x.DataBaseItemType == DataBaseItemType.Table);
                AppendTables(tables, item);
                //添加视图信息
                var views = dbInfos.Details.FindAll(x=>x.DataBaseItemType == DataBaseItemType.View);
                AppendViews(views, item);
                //添加存储过程信息
                var procedures = dbInfos.Details.FindAll(x=>x.DataBaseItemType == DataBaseItemType.Procedure);
                AppendProcedures(views, item);
            }
        }
        private void AppendTables(List<DataBaseItemView> tables, ExprItem parentItem)
        {
            var itemName = "Table";
            var childExprItem = new ExprItem()
            {
                ID = itemName,
                Code = itemName,
                Name = itemName,
                DisplayName = itemName,
                ItemType = ItemType.Object,
                ValueType = DataType.List,
                HelpInfo = itemName,
                SortOrder = 0,
                ExprMetaDataID = "",
                ParentID = parentItem.ID,
                DataModels = itemName,
                IsLeaf = (tables!=null && tables.Count>0)?false:true
            };
            AppendItemByDBDetails(tables, childExprItem);
            parentItem.Children.Add(childExprItem);
        }
        private void AppendViews(List<DataBaseItemView> tables, ExprItem parentItem)
        {
            var itemName = "View";
            var childExprItem = new ExprItem()
            {
                ID = itemName,
                Code = itemName,
                Name = itemName,
                DisplayName = itemName,
                ItemType = ItemType.Object,
                ValueType = DataType.List,
                HelpInfo = itemName,
                SortOrder = 1,
                ExprMetaDataID = "",
                ParentID = parentItem.ID,
                DataModels = itemName,
                IsLeaf = (tables != null && tables.Count > 0) ? false : true
            };
            AppendItemByDBDetails(tables, childExprItem);
            parentItem.Children.Add(childExprItem);
        }
        private void AppendProcedures(List<DataBaseItemView> tables, ExprItem parentItem)
        {
            var itemName = "Procedure";
            var childExprItem = new ExprItem()
            {
                ID = itemName,
                Code = itemName,
                Name = itemName,
                DisplayName = itemName,
                ItemType = ItemType.Object,
                ValueType = DataType.List,
                HelpInfo = itemName,
                SortOrder = 2,
                ExprMetaDataID = "",
                ParentID = parentItem.ID,
                DataModels = itemName,
                IsLeaf = (tables != null && tables.Count > 0) ? false : true
            };
            AppendItemByDBDetails(tables, childExprItem);
            parentItem.Children.Add(childExprItem);
        }
        private void AppendItemByDBDetails(List<DataBaseItemView> details, ExprItem parentItem)
        {
            var sortDetails = details.OrderBy(x=>x.SortOrder).ToList();
            sortDetails.ForEach(d=>
            {
                var childExprItem = new ExprItem()
                {
                    ID = d.ID,
                    Code = d.Code,
                    Name = d.Name,
                    DisplayName = d.Name,
                    ItemType = ItemType.Object,
                    ValueType = DataType.Record,
                    HelpInfo = d.Description,
                    SortOrder = d.SortOrder,
                    ExprMetaDataID = "",
                    ParentID = parentItem.ID,
                    IsLeaf = (d.Details != null && d.Details.Count > 0) ? false : true,
                };
                if (!childExprItem.IsLeaf)
                {
                    AppendItemByDBDetails(d.Details,childExprItem);
                }
                parentItem.Children.Add(childExprItem);
            });
        }

        private DataBaseInfoView GetDataBaseInfo(ExprItem item,string projectBranchId)
        {
            var projectBranch = new ProjectBranchManager().GetProjectBranch(projectBranchId);
            if (projectBranch != null)
            {
                var project = new DevMetadataService().GetMetadata(projectBranch.ProjectID, projectBranchId) as FASProjectMetaData;
                var curEnvironment = new EnvironmentManager().GetEnvironment(projectBranch.EnvironmentID);
                if (project != null && curEnvironment != null && !string.IsNullOrEmpty(curEnvironment.PublishURL))
                {
                    return GetDataBaseInfoFromDebugEnvironment(item,curEnvironment.PublishURL, project.DevAppID);
                }
            }
            return Demo();
            //return new DataBaseInfoView();
        }
        private DataBaseInfoView GetDataBaseInfoFromDebugEnvironment(ExprItem item,string publishUrl,string devAppID)
        {
            var dbCodes = new List<string>() { item.Code };
            var filterDic = new Dictionary<string, object>();
            filterDic.Add("dbCodes", dbCodes);
            string SID_GetDBInfoViews = "FASR-GetDBInfoViews";
            var result = new SGInvoker().Post(publishUrl, devAppID, SID_GetDBInfoViews, filterDic);
            var views = JsonConvert.DeserializeObject<List<DataBaseInfoView>>(result.data);
            return views[0];

        }
        private DataBaseInfoView Demo()
        {
            var info = new DataBaseInfoView()
            {
                ID = "TeldMaster",
                Code = "TeldMaster",
                Name = "TeldMaster",
                Description = "TeldMaster",
            };
            info.Details = new List<DataBaseItemView>();
            for (int i = 0; i < 10; i++)
            {
                var tbName = "Table" + i;
                var table = new DataBaseItemView()
                {
                    ID = tbName,
                    Code = tbName,
                    Name = tbName,
                    Description = tbName,
                    DataBaseItemType = DataBaseItemType.Table,
                    SortOrder =i,
                };
                for (int j = 0; j < 20; j++)
                {
                    var colName = "Col"+i.ToString()+j.ToString();
                    var col = new DataBaseItemView()
                    {
                        ID = colName,
                        Code = colName,
                        Name = colName,
                        Description = colName,
                        DataBaseItemType = DataBaseItemType.Column,
                        SortOrder = j,
                        IsPrimaryKey = (j ==0),
                        DataType = "Varchar",
                    };
                    if (table.Details == null)
                        table.Details = new List<DataBaseItemView>();
                    table.Details.Add(col);
                }
                info.Details.Add(table);

                var vwName = "View"+i;
                var view = new DataBaseItemView()
                {
                    ID = vwName,
                    Code = vwName,
                    Name = vwName,
                    Description = vwName,
                    DataBaseItemType = DataBaseItemType.View,
                    SortOrder = i,
                };
                info.Details.Add(view);

                var procName = "Proc" + i;
                var proc = new DataBaseItemView()
                {
                    ID = procName,
                    Code = procName,
                    Name = procName,
                    Description = procName,
                    DataBaseItemType = DataBaseItemType.Procedure,
                    SortOrder = i,
                };
                info.Details.Add(proc);
            }
            return info;
        }

        private string GetCurDebugEnvironmentUrl(string projectID)
        {
            return "";
        }
        #endregion
    }
}
